package com.yuexunxinxi.carefree.utils;

import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import org.springframework.beans.factory.annotation.Value;

import javax.annotation.PostConstruct;
import java.util.*;

/**
 * 作者: 李咨辰
 * 文件名: RedisUtil.java
 * 路径: com.yuntu.redisdemo.demos.web
 * 时间: 2024-05-27 11:38
 * 版本: 1.0
 * 描述: TODO Redis
 **/
@Component
public class RedisUtil {
    private static JedisPool jedisPool;

    @Value("${server.host}")
    private String HOST;
    @Value("${redis.password}")
    private String PASSWORD;
    @Value("${redis.port}")
    private int PORT;

    @PostConstruct
    public void init() {
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        poolConfig.setMaxTotal(10000); // 设置最大连接数
        poolConfig.setMaxIdle(50); // 设置最大空闲连接数
        jedisPool = new JedisPool(poolConfig, HOST, PORT, 0, PASSWORD);
    }

    public static Jedis getJedis() {
        return jedisPool.getResource();
    }

    /**
     * 判断是否存在
     *
     * @param key 健
     * @return 存在true 不存在false
     */
    public static Boolean exists(String key) {
        Jedis jedis = null;
        Boolean exists;
        try {
            jedis = getJedis();
            exists = jedis.exists(key);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return exists;
    }

    /**
     * 设置字符串键值对(添加)
     *
     * @param key   健
     * @param value 值
     * @return 成功true 失败false
     */
    public static Boolean set(String key, String value) {
        Jedis jedis = null;
        String set;
        try {
            jedis = getJedis();
            set = jedis.set(key, value);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return set.equals("OK") || set.equals("ok");
    }


    /**
     * 设置字符串键值对，并设置过期时间（秒）
     *
     * @param key     键
     * @param value   值
     * @param seconds 过期时间（秒）
     * @return 成功true 失败false
     */
    public static boolean setStringWithExpire(String key, String value, int seconds) {
        Jedis jedis = null;
        String set;
        try {
            jedis = getJedis();
            set = jedis.setex(key, seconds, value);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return set.equals("OK") || set.equals("ok");
    }


    /**
     * 获取字符串键对应的值
     *
     * @param key 健
     * @return 值
     */
    public static String get(String key) {
        Jedis jedis = null;
        String value;
        try {
            jedis = getJedis();
            value = jedis.get(key);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return value;
    }

    /**
     * 设置过期时间
     *
     * @param key     健
     * @param seconds 时间(秒)
     * @return 成功多少条数据
     */
    public static int expire(String key, int seconds) {
        Jedis jedis = null;
        int set;
        try {
            jedis = getJedis();
            set = jedis.expire(key, seconds).intValue();
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return set;
    }

    /**
     * 查询剩余过期时间
     *
     * @param key 健
     * @return 时间(秒)
     */
    public static Integer getTTL(String key) {
        Jedis jedis = null;
        int set;
        try {
            jedis = getJedis();
            set = jedis.ttl(key).intValue();
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return set;
    }

    /**
     * 查询剩余过期时间
     *
     * @param key 健
     * @return 时间(秒)
     */
    public static Integer delKey(String key) {
        Jedis jedis = null;
        int set;
        try {
            jedis = getJedis();
            set = jedis.del(key).intValue();
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return set;
    }


    /**
     * 将一个或多个值插入到列表尾部
     *
     * @param key    列表键
     * @param values 要插入的值数组
     * @return 操作后列表的长度
     */
    public static long pushListToTail(String key, String[] values) {
        Jedis jedis = null;
        long rpush;
        try {
            jedis = getJedis();
            rpush = jedis.rpush(key, values);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return rpush;
    }

    /**
     * 获取列表指定范围内的元素
     *
     * @param key   列表键
     * @param start 起始索引，0表示第一个元素，-1表示最后一个元素等
     * @param end   结束索引
     * @return 元素数组
     */
    public static List<String> getListRange(String key, int start, int end) {
        Jedis jedis = null;
        List<String> lrange;

        try {
            jedis = getJedis();
            lrange = jedis.lrange(key, start, end);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return lrange;
    }


    /**
     * 将一个或多个元素添加到集合中
     *
     * @param key    集合键
     * @param values 要添加的元素数组
     * @return 实际添加到集合中的元素数量
     */
    public static long addToSet(String key, String[] values) {
        Jedis jedis = null;
        long sadd;
        try {
            jedis = getJedis();
            sadd = jedis.sadd(key, values);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return sadd;
    }

    /**
     * 判断元素是否在集合中
     *
     * @param key   集合键
     * @param value 要判断的元素
     * @return 如果元素在集合中则返回true，否则返回false
     */
    public static boolean isInSet(String key, String value) {
        Jedis jedis = null;
        boolean sismember;
        try {
            jedis = getJedis();
            sismember = jedis.sismember(key, value);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return sismember;
    }


    /**
     * 获取集合中的所有元素
     *
     * @param key 集合键
     * @return 元素数组
     */
    public static Set<String> getSetMembers(String key) {
        Jedis jedis = null;
        Set<String> smembers;
        try {
            jedis = getJedis();
            smembers = jedis.smembers(key);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return smembers;
    }


    /**
     * 设置哈希表中的键值对
     *
     * @param key   哈希表键
     * @param field 哈希表中的字段
     * @param value 哈希表中字段对应的值
     * @return .
     */
    public static Long setHashValue(String key, String field, String value) {
        Jedis jedis = null;
        Long hset;
        try {
            jedis = getJedis();
            hset = jedis.hset(key, field, value);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return hset;
    }

    /**
     * 获取哈希表中的所有字段和值
     *
     * @param key 哈希表键
     * @return 包含字段和值的Map，这里用Java的Map形式模拟，实际可根据需求转换
     */
    public static Map<String, String> getHashAll(String key) {
        Jedis jedis = null;
        Map<String, String> result = new HashMap<>();
        try {
            jedis = getJedis();

            Map<String, String> hashMap = jedis.hgetAll(key);
            result.putAll(hashMap);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return result;
    }


    /**
     * 获取有序集合中指定分数范围内的成员
     *
     * @param key      有序集合键
     * @param minScore 最小分数
     * @param maxScore 最大分数
     * @return 成员数组
     */
    public static Set<String> getZSetRangeByScore(String key, double minScore, double maxScore) {
        Jedis jedis = null;
        Set<String> zrangeByScore;
        try {
            jedis = getJedis();
            zrangeByScore = jedis.zrangeByScore(key, minScore, maxScore);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return zrangeByScore;
    }

    /**
     * 获取有序集合中指定排名范围内的成员
     *
     * @param key       有序集合键
     * @param startRank 起始排名，0表示第一名
     * @param endRank   结束排名
     * @return 成员数组
     */
    public static Set<String> getZSetRangeByRank(String key, int startRank, int endRank) {
        Jedis jedis = null;
        Set<String> zrange;
        try {
            jedis = getJedis();
            zrange = jedis.zrange(key, startRank, endRank);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return zrange;
    }

}
